#include <iostream>
#include <pthread.h>
#include <functional>
#include <semaphore.h>

using namespace std;

typedef void*(*func_t)(void*);

sem_t PA;
sem_t PB;
sem_t PC;
pthread_mutex_t mtx;

void* printA(void* args)
{
    while(1)
    {
        sem_wait(&PA);
        pthread_mutex_lock(&mtx);
        
        cout<<"A"<<endl;
        sem_post(&PB);
        pthread_mutex_unlock(&mtx);
    }
    return nullptr;
}

void* printB(void* args)
{
    while(1)
    {
        sem_wait(&PB);
        pthread_mutex_lock(&mtx);
        
        cout<<"B"<<endl;
        sem_post(&PC);
        pthread_mutex_unlock(&mtx);
    }
    return nullptr;
}

void* printC(void* args)
{
    while(1)
    {
        sem_wait(&PC);
        pthread_mutex_lock(&mtx);
        
        cout<<"C"<<endl;
        sem_post(&PA);
        pthread_mutex_unlock(&mtx);
    }
    return nullptr;
}

int main()
{

    
    sem_init(&PA,0,1);
    sem_init(&PB,0,0);
    sem_init(&PC,0,0);
    pthread_mutex_init(&mtx,nullptr);
    func_t callbackarr[3] = {printA,printB,printC};
    pthread_t threadarr[3];
    sem_t semarr[3] = {PA,PB,PC};
    for(int i = 0;i<3;i++)
    {

        pthread_create(&(threadarr[i]),nullptr,callbackarr[i],nullptr);
    }

    pthread_join(threadarr[0],nullptr);
    pthread_join(threadarr[1],nullptr);
    pthread_join(threadarr[2],nullptr);

    pthread_mutex_destroy(&mtx);
    sem_destroy(&PA);
    sem_destroy(&PB);
    sem_destroy(&PC);
    return 0;                
}